<!DOCTYPE html>
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  <meta name="description" content="刘清政">
  <meta name="keyword" content="hexo-theme">
  
    <link rel="shortcut icon" href="/css/images/logo.png">
  
  <title>
    
      Go包管理 | Justin-刘清政的博客
    
  </title>
  <link href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link href="//cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css" rel="stylesheet">
  <link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/tomorrow.min.css" rel="stylesheet">
  
<link rel="stylesheet" href="/css/style.css">

  
    
<link rel="stylesheet" href="/css/plugins/gitment.css">

  
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/geopattern/1.2.3/js/geopattern.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script>
  
    
<script src="/js/qrious.js"></script>

  
  
    
<script src="/js/gitment.js"></script>

  
  

  
<meta name="generator" content="Hexo 4.2.0"></head>
<div class="wechat-share">
  <img src="/css/images/logo.png" />
</div>

  <body>
    <header class="header fixed-header">
  <div class="header-container">
    <a class="home-link" href="/">
      <div class="logo"></div>
      <span>Justin-刘清政的博客</span>
    </a>
    <ul class="right-list">
      
        <li class="list-item">
          
            <a href="/" class="item-link">主页</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/tags/" class="item-link">标签</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/archives/" class="item-link">归档</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/about/" class="item-link">关于我</a>
          
        </li>
      
    </ul>
    <div class="menu">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </div>
    <div class="menu-mask">
      <ul class="menu-list">
        
          <li class="menu-item">
            
              <a href="/" class="menu-link">主页</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/tags/" class="menu-link">标签</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/archives/" class="menu-link">归档</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/about/" class="menu-link">关于我</a>
            
          </li>
        
      </ul>
    </div>
  </div>
</header>

    <div id="article-banner">
  <h2>Go包管理</h2>



  <p class="post-date">2019-03-10</p>
    <!-- 不蒜子统计 -->
    <span id="busuanzi_container_page_pv" style='display:none' class="">
        <i class="icon-smile icon"></i> 阅读数：<span id="busuanzi_value_page_pv"></span>次
    </span>
  <div class="arrow-down">
    <a href="javascript:;"></a>
  </div>
</div>
<main class="app-body flex-box">
  <!-- Article START -->
  <article class="post-article">
    <section class="markdown-content"><h2 id="一-包管理历史"><a href="#一-包管理历史" class="headerlink" title="一 包管理历史"></a>一 包管理历史</h2><p>Golang 的包管理一直被大众所诟病的一个点，但是我们可以看到现在确实是在往好的方向进行发展。下面是官方的包管理工具的发展历史：</p>
<ul>
<li>在 1.5 版本之前，所有的依赖包都是存放在 GOPATH 下，没有版本控制。这个类似 Google  使用单一仓库来管理代码的方式。这种方式的最大的弊端就是无法实现包的多版本控制，比如项目 A 和项目 B 依赖于不同版本的 package，如果  package 没有做到完全的向前兼容，往往会导致一些问题。</li>
<li>1.5 版本推出了 vendor 机制。所谓 vendor 机制，就是每个项目的根目录下可以有一个 vendor 目录，里面存放了该项目的依赖的 package。<code>go build</code> 的时候会先去 vendor 目录查找依赖，如果没有找到会再去 GOPATH 目录下查找。</li>
<li>1.9 版本推出了实验性质的包管理工具 dep，这里把 dep 归结为 Golang 官方的包管理方式可能有一些不太准确。关于 dep 的争议颇多，比如为什么官方后来没有直接使用 dep 而是弄了一个新的 modules，具体细节这里不太方便展开。</li>
<li>1.11 版本推出 modules 机制，简称 mod。modules 的原型其实是 vgo，关于 vgo，可以自行搜索。</li>
</ul>
<p>除此之外，社区也一直在有几个活跃的包管理工具，使用广泛且具有代表性的主要有下面几个：</p>
<ul>
<li>godep</li>
<li>glide</li>
<li>govendor</li>
</ul>
<h2 id="二-modules-的使用"><a href="#二-modules-的使用" class="headerlink" title="二 modules 的使用"></a>二 modules 的使用</h2><h3 id="2-1-准备"><a href="#2-1-准备" class="headerlink" title="2.1 准备"></a>2.1 准备</h3><p>Golang 版本：1.12.3。在 1.12 版本之前，使用 Go modules 之前需要环境变量 GO111MODULE:</p>
<ul>
<li>GO111MODULE=off: 不使用 modules 功能，查找vendor和GOPATH目录</li>
<li>GO111MODULE=on: 使用 modules 功能，不会去 GOPATH 下面查找依赖包。</li>
<li>GO111MODULE=auto: Golang 自己检测是不是使用 modules 功能，如果当前目录不在$GOPATH <strong>并且</strong> 当前目录（或者父目录）下有go.mod文件，则使用 GO111MODULE， 否则仍旧使用 GOPATH mode</li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">set GO111MODULE=on    <span class="comment">//windows</span></span><br><span class="line">export GO111MODULE=on <span class="comment">//linux</span></span><br></pre></td></tr></table></figure>

<p>在 GOPATH 之外创建一个项目 mod-demo，包含一个 main.go 文件，内容如下:</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">"fmt"</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"github.com/astaxie/beego"</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">	fmt.Println(<span class="string">"hello"</span>)</span><br><span class="line">	beego.Run()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-2-初始化go-modules"><a href="#2-2-初始化go-modules" class="headerlink" title="2.2 初始化go modules"></a>2.2 初始化go modules</h3><p>在项目根目录执行命令 <code>go mod init test-demo</code> ，然后会生成一个 go.mod</p>
<p><img src="https://tva1.sinaimg.cn/large/006y8mN6gy1g94t8ve4vqj30pu05gmy8.jpg" alt="image-20191120210941001"></p>
<p>这里比较关键的就是这个 go.mod 文件，这个文件中标识了我们的项目的依赖的 package 的版本。执行 init  暂时还没有将所有的依赖管理起来。我们需要将程序 run 起来（比如执行 go run/test），或者 build（执行命令 go  build）的时候，才会触发依赖的解析。</p>
<p>比如使用 go run 即可触发 modules 工作。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">go</span> run test.<span class="keyword">go</span></span><br></pre></td></tr></table></figure>

<p>这个时候我们再查看 go.mod 文件：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">module test-demo</span><br><span class="line"></span><br><span class="line">go 1.13</span><br><span class="line"></span><br><span class="line">require (</span><br><span class="line">	github.com&#x2F;astaxie&#x2F;beego v1.12.0 &#x2F;&#x2F; indirect</span><br><span class="line">	github.com&#x2F;shiena&#x2F;ansicolor v0.0.0-20151119151921-a422bbe96644 &#x2F;&#x2F; indirect</span><br><span class="line">)</span><br></pre></td></tr></table></figure>

<p><strong>注意：有indirect注释的代表间接依赖，没有的代表直接依赖，这里是版本号+时间戳+hash</strong></p>
<p><strong>注意：在goland中可以用alt+enter/option+enter来下载依赖包</strong></p>
<p>同时我们发现项目目录下多了一个 go.sum 用来记录每个 package 的版本和哈希值。go.mod 文件正常情况会包含 module 和 require 模块，除此之外还可以包含 replace 和 exclude 模块。</p>
<p>这些 package 并不是直接存储到 GOPATH/src，而是存储到 GOPATH/pkg/mod 下面，不同版本并存的方式。</p>
<p><img src="https://tva1.sinaimg.cn/large/006y8mN6gy1g94te0hhiwj30qg0fs77y.jpg" alt="image-20191120211440359"></p>
<h3 id="2-3-依赖的升级和降级"><a href="#2-3-依赖的升级和降级" class="headerlink" title="2.3 依赖的升级和降级"></a>2.3 依赖的升级和降级</h3><p>可以使用如下命令来查看当前项目依赖的所有的包</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">go</span> list -m -u all</span><br><span class="line"><span class="comment">//如果我想要升级（降级）某个 package 则只需要 go get 即可，比如：</span></span><br><span class="line"><span class="keyword">go</span> get <span class="keyword">package</span>@version</span><br></pre></td></tr></table></figure>

<p>需要注意的是，在 modules 模式开启和关闭的情况下，<code>go get</code> 的使用方式不是完全相同的。在 modules 模式开启的情况下，可以通过在 package 后面添加 <em>@version</em>  来表明要升级（降级）到某个版本。如果没有指明 version 的情况下，则默认先下载打了 tag 的 release 版本，比如 v0.4.5  或者 v1.2.3；如果没有 release 版本，则下载最新的 pre release 版本，比如  v0.0.1-pre1。如果还没有则下载最新的 commit。这个地方给我们的一个启示是如果我们不按规范的方式来命名我们的 package 的  tag，则 modules 是无法管理的。version 的格式为 <code>v(major).(minor).(patch)</code> ，更多信息可以参考：<a href="https://semver.org/" target="_blank" rel="noopener">https://semver.org/</a> 。</p>
<p>比如我们现在想将我们依赖中的 beego 项目的版本改为 v1.11.1，则可以像如下操作。我们发现执行完 <code>go get</code> 之后， go.mod 中的项目的版本也相应改变了。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">go</span> get github.com/astaxie/beego@v1<span class="number">.11</span><span class="number">.1</span></span><br></pre></td></tr></table></figure>

<p>在 modules 开启的模式下，go get 还支持 version 模糊查询，比如 &gt; v1.0.0 表示大于 v1.0.0<br>的可使用版本；&lt; v1.12.0 表示小于 v1.12.0  版本下最近可用的版本。version 的比较规则按照 version<br>的各个字段来展开。</p>
<p>除了指定版本，我们还可以使用如下命名使用最近的可行的版本：</p>
<ul>
<li>go get -u 使用最新的 minor 或者 patch 版本</li>
<li>go get -u=patch 使用最新的 patch 版本</li>
</ul>
<h3 id="2-4-vender"><a href="#2-4-vender" class="headerlink" title="2.4 vender"></a>2.4 vender</h3><p>我们知道 Go 1.5 推出了 vendor 机制，go mod 也可以支持 vendor 机制，将依赖包拷贝到 vendor 目录。但是像一些 test case 里面的依赖包并不会拷贝的 vendor 目录中。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">go</span> mod vendor</span><br></pre></td></tr></table></figure>

<p>##三 modules 高级特性</p>
<p>###3.1 代理服务器GoProxy</p>
<p>proxy 顾名思义，代理服务器。众所周知，有些 Golang 的 package 在国内是无法直接 go get  的。在之前，我们解决这个问题，一般都是通过设置 http_proxy/https_proxy 来解决。GoProxy 相当于官方提供了一种  proxy 的方式让用户来进行包下载。要使用 GoProxy 只需要设置环境变量 <code>GOPROXY</code> 即可。目前公开的 GOPROXY 有：</p>
<ul>
<li>goproxy.io     <strong>在goland–&gt;Go–&gt;Go Modules(ego)中配置这个地址</strong></li>
<li>goproxy.cn: 由七牛云提供，参考 github repo</li>
</ul>
<p><img src="https://tva1.sinaimg.cn/large/006y8mN6gy1g94wsfd7ybj31io08yq4i.jpg" alt="image-20191120231215167"></p>
<p>当然你也可以实现自己的 GoProxy 服务，比如项目中的依赖包含外部依赖和内部依赖的时候，那么只需要实现 module proxy protocal 协议即可。</p>
<p>值得注意的是，在最新 release 的 Go 1.13 版本中默认将 GOPROXY 设置为 <a href="https://proxy.golang.org，这个对于国内的开发者是无法直接使用的。所以如果升级了" target="_blank" rel="noopener">https://proxy.golang.org，这个对于国内的开发者是无法直接使用的。所以如果升级了</a> Go 1.13 版本一定要把 GOPROXY 手动改掉。</p>
<h3 id="3-2-replace"><a href="#3-2-replace" class="headerlink" title="3.2 replace"></a>3.2 replace</h3><p>replace 主要为了解决某些包发生改名的问题。</p>
<p>对于另外一种场景有的时候也是有用的，比如对于有些 golang.org/x/ 下面的包由于某些原因在国内是下载不了的，但是对应的包在 github 上面是有一份拷贝的，这个时候我们就可以将 go.mod 中的包进行 replace 操作。</p>
<p>下面是一个 Beego 项目的 go.mod 的 replace 的示例。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">replace golang.org/x/crypto v0<span class="number">.0</span><span class="number">.0</span><span class="number">-20181127143415</span>-eb0de9b17e85 =&gt; github.com/golang/crypto v0<span class="number">.0</span><span class="number">.0</span><span class="number">-20181127143415</span>-eb0de9b17e85</span><br><span class="line">replace gopkg.in/yaml.v2 v2<span class="number">.2</span><span class="number">.1</span> =&gt; github.com/<span class="keyword">go</span>-yaml/yaml v0<span class="number">.0</span><span class="number">.0</span><span class="number">-20180328195020</span><span class="number">-5420</span>a8b6744d</span><br></pre></td></tr></table></figure>

<h3 id="3-3-SubCommand"><a href="#3-3-SubCommand" class="headerlink" title="3.3 SubCommand"></a>3.3 SubCommand</h3><p>modules 支持的 subcommand 如下</p>
<p>即输入<code>go mod</code>后面可以跟以下命令</p>
<ul>
<li>download: 下载 modules 到本地缓存</li>
<li>edit: 提供一种命令行交互修改 go.mod 的方式</li>
<li>graph: 将 module 的依赖图在命令行打印出来，其实并不是很直观</li>
<li>init: 初始化 modules，会生成一个 go.mod 文件</li>
<li>tidy: 清理 go.mod 中的依赖，会添加缺失的依赖，同时移除没有用到的依赖</li>
<li>vendor: 将依赖包打包拷贝到项目的 vendor 目录下，值得注意的是并不会将 test code 中的依赖包打包到 vendor 中。这种设计在社区也引起过几次争论，但是并没有达成一致。</li>
<li>verify: verify 用来检测依赖包自下载之后是否被改动过。</li>
<li>why: 解释为什么 package 或者 module 是需要，但是看上去解释的理由并不是非常的直观。</li>
</ul>
<h2 id="四-Go-1-13-对-modules-的改动"><a href="#四-Go-1-13-对-modules-的改动" class="headerlink" title="四 Go 1.13 对 modules 的改动"></a>四 Go 1.13 对 modules 的改动</h2><p>上面在讨论 GoProxy 的时候提到了 Go 1.13 默认设置环境变量 GOPROXY 的值，除此之外 Go 1.13 对 modules 还有哪些值得注意的改动呢？</p>
<p>###4.1 默认开启</p>
<p>modules 在 Go 1.13 的版本下是默认开启的。</p>
<p>###4.2 GOPRIVATE</p>
<p>前面也说到对于一些内部的 package，GoProxy 并不能很好的处理，Go 1.13 推出了 GOPRIVATE  机制。只需要设置这个环境变量，然后标识出哪些 package 是 private 的，那么对于这个 package 的处理将不会从 proxy  下载。GOPRIVATE 的值是一个以逗号分隔的列表，支持正则（正则语法遵守 Golang 的 包 path.Match）。下面是一个  GOPRIVATE 的示例：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GOPRIVATE=*.corp.example.com,rsc.io/private</span><br></pre></td></tr></table></figure>

<p>上面的 GOPRIVATE 表示以 *.corp.example.com 或者 rsc.io/private 开头的 package 都是私有的。</p>
<p>###4.3 GOSUMDB</p>
<p>GOSUMDB 的全称为 Go CheckSum Database，用来下载的包的安全性校验问题。包的安全性在使用 GoProxy  之后更容易出现，比如我们引用了一个不安全的 GoProxy 之后然后下载了一个不安全的包，这个时候就出现了安全性问题。对于这种情况，可以通过  GOSUMDB 来对包的哈希值进行校验。当然如果想要关闭哈希校验，可以将 GOSUMDB 设置为  off；如果要对部分包关闭哈希校验，则可以将包的前缀设置到环境变量中 GONOSUMDB 中，设置规则类似 GOPRIVATE。</p>
<p>关于 GOSUMDB 的配置格式为：<db_name>+<publickey>+<url>。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GOSUMDB&#x3D;&quot;sum.golang.org&quot;GOSUMDB&#x3D;&quot;sum.golang.org+&lt;publickey&gt;&quot;GOSUMDB&#x3D;&quot;sum.golang.org+&lt;publickey&gt; https:&#x2F;&#x2F;sum.golang.org&quot;</span><br></pre></td></tr></table></figure>

<p>上面三种配置都是合理的，因为对于 sum.golang.org，Go 自己知道其对应的 publickey 和  url，所以我们只要配置一个名字即可，对于另外一个 sum.golang.google.cn 也是一样。除此之外的，都需要指明  publickey，url 默认是 https://<db_name>。</p>
<p>关于 GOSUMDB 更多的详细信息可以参考：<a href="https://golang.org/cmd/go/#hdr-Module_authentication_failures" target="_blank" rel="noopener">https://golang.org/cmd/go/#hdr-Module_authentication_failures</a></p>
<h2 id="五-自己写的包如何导入使用"><a href="#五-自己写的包如何导入使用" class="headerlink" title="五 自己写的包如何导入使用"></a>五 自己写的包如何导入使用</h2><p>直接在go.mod中写包名即可</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">module test-demo</span><br><span class="line"></span><br><span class="line"><span class="keyword">go</span> <span class="number">1.13</span></span><br><span class="line"></span><br><span class="line">require (</span><br><span class="line">	github.com/astaxie/beego v1<span class="number">.12</span><span class="number">.0</span></span><br><span class="line">	github.com/gin-gonic/gin v1<span class="number">.4</span><span class="number">.0</span> <span class="comment">// indirect</span></span><br><span class="line">	github.com/<span class="keyword">go</span>-redis/redis v6<span class="number">.15</span><span class="number">.6</span>+incompatible</span><br><span class="line">	github.com/shiena/ansicolor v0<span class="number">.0</span><span class="number">.0</span><span class="number">-20151119151921</span>-a422bbe96644 <span class="comment">// indirect</span></span><br><span class="line">    redisPackage v0<span class="number">.0</span><span class="number">.1</span>  <span class="comment">//自己加的v0.1.1 必须为三个数(也可以 不加)</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure>



<h2 id="五-总结"><a href="#五-总结" class="headerlink" title="五 总结"></a>五 总结</h2><p>Golang 包管理历经多个版本，目前来看并没有一个完全让开发者满意的方案，比如类似 Java 的 maven  的包管理方式。很多开发者也表示 modules 的管理方式也不是很直观。其实 Golang 的 package 使用 git  的管理方式来管理其实是一个很好的管理方式，我们最需要的其实如何能让普通开发者获取到任何 package  的心智负担降到最低。值得欣慰的是我们确实有看到大家在这个方向上的努力，比如 modules 的 GoProxy。</p>
<p>放眼未来，希望会有一种令大部分普通开发者满意的包管理方式吧。</p>
<h2 id="最后常用命令"><a href="#最后常用命令" class="headerlink" title="最后常用命令"></a>最后常用命令</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">go</span> mod init:初始化modules</span><br><span class="line"><span class="keyword">go</span> mod download:下载modules到本地cache</span><br><span class="line"><span class="keyword">go</span> mod edit:编辑<span class="keyword">go</span>.mod文件，选项有-json、-require和-exclude，可以使用帮助<span class="keyword">go</span> help mod edit</span><br><span class="line"><span class="keyword">go</span> mod graph:以文本模式打印模块需求图</span><br><span class="line"><span class="keyword">go</span> mod tidy:检查，删除错误或者不使用的modules，下载没download的<span class="keyword">package</span></span><br><span class="line"><span class="keyword">go</span> mod vendor:生成vendor目录</span><br><span class="line"><span class="keyword">go</span> mod verify:验证依赖是否正确</span><br><span class="line"><span class="keyword">go</span> mod why：查找依赖</span><br><span class="line"></span><br><span class="line"><span class="keyword">go</span> test    执行一下，自动导包</span><br><span class="line"></span><br><span class="line"><span class="keyword">go</span> list -m  主模块的打印路径</span><br><span class="line"><span class="keyword">go</span> list -m -f=&#123;&#123;.Dir&#125;&#125;  <span class="built_in">print</span>主模块的根目录</span><br><span class="line"><span class="keyword">go</span> list -m all  查看当前的依赖和版本信息</span><br></pre></td></tr></table></figure>

</section>
    <!-- Tags START -->
    
      <div class="tags">
        <span>Tags:</span>
        
  <a href="/tags#Go" >
    <span class="tag-code">Go</span>
  </a>

      </div>
    
    <!-- Tags END -->
    <!-- NAV START -->
    
  <div class="nav-container">
    <!-- reverse left and right to put prev and next in a more logic postition -->
    
      <a class="nav-left" href="/go/3-Go%E8%AF%AD%E8%A8%80%E5%B8%B8%E7%94%A8%E6%A0%87%E5%87%86%E5%BA%93/03-Go%E8%AF%AD%E8%A8%80%E4%B9%8Bfmt/">
        <span class="nav-arrow">← </span>
        
          Go语言之fmt
        
      </a>
    
    
      <a class="nav-right" href="/go/5-Go%E8%AF%AD%E8%A8%80%E8%BF%9B%E9%98%B6/01-Go%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/">
        
          Go内存模型
        
        <span class="nav-arrow"> →</span>
      </a>
    
  </div>

    <!-- NAV END -->
    <!-- 打赏 START -->
    
      <div class="money-like">
        <div class="reward-btn">
          赏
          <span class="money-code">
            <span class="alipay-code">
              <div class="code-image"></div>
              <b>使用支付宝打赏</b>
            </span>
            <span class="wechat-code">
              <div class="code-image"></div>
              <b>使用微信打赏</b>
            </span>
          </span>
        </div>
        <p class="notice">点击上方按钮,请我喝杯咖啡！</p>
      </div>
    
    <!-- 打赏 END -->
    <!-- 二维码 START -->
    
      <div class="qrcode">
        <canvas id="share-qrcode"></canvas>
        <p class="notice">扫描二维码，分享此文章</p>
      </div>
    
    <!-- 二维码 END -->
    
      <!-- Gitment START -->
      <div id="comments"></div>
      <!-- Gitment END -->
    
  </article>
  <!-- Article END -->
  <!-- Catalog START -->
  
    <aside class="catalog-container">
  <div class="toc-main">
  <!-- 不蒜子统计 -->
    <strong class="toc-title">目录</strong>
    
      <ol class="toc-nav"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#一-包管理历史"><span class="toc-nav-text">一 包管理历史</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#二-modules-的使用"><span class="toc-nav-text">二 modules 的使用</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-1-准备"><span class="toc-nav-text">2.1 准备</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-2-初始化go-modules"><span class="toc-nav-text">2.2 初始化go modules</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-3-依赖的升级和降级"><span class="toc-nav-text">2.3 依赖的升级和降级</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-vender"><span class="toc-nav-text">2.4 vender</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#3-2-replace"><span class="toc-nav-text">3.2 replace</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#3-3-SubCommand"><span class="toc-nav-text">3.3 SubCommand</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#四-Go-1-13-对-modules-的改动"><span class="toc-nav-text">四 Go 1.13 对 modules 的改动</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#五-自己写的包如何导入使用"><span class="toc-nav-text">五 自己写的包如何导入使用</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#五-总结"><span class="toc-nav-text">五 总结</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#最后常用命令"><span class="toc-nav-text">最后常用命令</span></a></li></ol>
    
  </div>
</aside>
  
  <!-- Catalog END -->
</main>

<script>
  (function () {
    var url = 'http://www.liuqingzheng.top/go/7-其他/03-Go包管理详解/';
    var banner = ''
    if (banner !== '' && banner !== 'undefined' && banner !== 'null') {
      $('#article-banner').css({
        'background-image': 'url(' + banner + ')'
      })
    } else {
      $('#article-banner').geopattern(url)
    }
    $('.header').removeClass('fixed-header')

    // error image
    $(".markdown-content img").on('error', function() {
      $(this).attr('src', 'http://file.muyutech.com/error-img.png')
      $(this).css({
        'cursor': 'default'
      })
    })

    // zoom image
    $(".markdown-content img").on('click', function() {
      var src = $(this).attr('src')
      if (src !== 'http://file.muyutech.com/error-img.png') {
        var imageW = $(this).width()
        var imageH = $(this).height()

        var zoom = ($(window).width() * 0.95 / imageW).toFixed(2)
        zoom = zoom < 1 ? 1 : zoom
        zoom = zoom > 2 ? 2 : zoom
        var transY = (($(window).height() - imageH) / 2).toFixed(2)

        $('body').append('<div class="image-view-wrap"><div class="image-view-inner"><img src="'+ src +'" /></div></div>')
        $('.image-view-wrap').addClass('wrap-active')
        $('.image-view-wrap img').css({
          'width': `${imageW}`,
          'transform': `translate3d(0, ${transY}px, 0) scale3d(${zoom}, ${zoom}, 1)`
        })
        $('html').css('overflow', 'hidden')

        $('.image-view-wrap').on('click', function() {
          $(this).remove()
          $('html').attr('style', '')
        })
      }
    })
  })();
</script>


  <script>
    var qr = new QRious({
      element: document.getElementById('share-qrcode'),
      value: document.location.href
    });
  </script>



  <script>
    var gitmentConfig = "liuqingzheng";
    if (gitmentConfig !== 'undefined') {
      var gitment = new Gitment({
        id: "Go包管理",
        owner: "liuqingzheng",
        repo: "FuckBlog",
        oauth: {
          client_id: "32a4076431cf39d0ecea",
          client_secret: "94484bd79b3346a949acb2fda3c8a76ce16990c6"
        },
        theme: {
          render(state, instance) {
            const container = document.createElement('div')
            container.lang = "en-US"
            container.className = 'gitment-container gitment-root-container'
            container.appendChild(instance.renderHeader(state, instance))
            container.appendChild(instance.renderEditor(state, instance))
            container.appendChild(instance.renderComments(state, instance))
            container.appendChild(instance.renderFooter(state, instance))
            return container;
          }
        }
      })
      gitment.render(document.getElementById('comments'))
    }
  </script>




    <div class="scroll-top">
  <span class="arrow-icon"></span>
</div>
    <footer class="app-footer">
<!-- 不蒜子统计 -->
<span id="busuanzi_container_site_pv">
     本站总访问量<span id="busuanzi_value_site_pv"></span>次
</span>
<span class="post-meta-divider">|</span>
<span id="busuanzi_container_site_uv" style='display:none'>
     本站访客数<span id="busuanzi_value_site_uv"></span>人
</span>
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>



  <p class="copyright">
    &copy; 2021 | Proudly powered by <a href="https://www.cnblogs.com/xiaoyuanqujing" target="_blank">小猿取经</a>
    <br>
    Theme by <a href="https://www.cnblogs.com/xiaoyuanqujing" target="_blank" rel="noopener">小猿取经</a>
  </p>
</footer>

<script>
  function async(u, c) {
    var d = document, t = 'script',
      o = d.createElement(t),
      s = d.getElementsByTagName(t)[0];
    o.src = u;
    if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
    s.parentNode.insertBefore(o, s);
  }
</script>
<script>
  async("//cdnjs.cloudflare.com/ajax/libs/fastclick/1.0.6/fastclick.min.js", function(){
    FastClick.attach(document.body);
  })
</script>

<script>
  var hasLine = 'true';
  async("//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js", function(){
    $('figure pre').each(function(i, block) {
      var figure = $(this).parents('figure');
      if (hasLine === 'false') {
        figure.find('.gutter').hide();
      }
      var lang = figure.attr('class').split(' ')[1] || 'code';
      var codeHtml = $(this).html();
      var codeTag = document.createElement('code');
      codeTag.className = lang;
      codeTag.innerHTML = codeHtml;
      $(this).attr('class', '').empty().html(codeTag);
      figure.attr('data-lang', lang.toUpperCase());
      hljs.highlightBlock(block);
    });
  })
</script>





<!-- Baidu Tongji -->

<script>
    var _baId = 'c5fd96eee1193585be191f318c3fa725';
    // Originial
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "//hm.baidu.com/hm.js?" + _baId;
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
</script>


<script src="/js/script.js"></script>


<script src="/js/search.js"></script>


<script src="/js/load.js"></script>



  <span class="local-search local-search-google local-search-plugin" style="right: 50px;top: 70px;;position:absolute;z-index:2;">
      <input type="search" placeholder="站内搜索" id="local-search-input" class="local-search-input-cls" style="">
      <div id="local-search-result" class="local-search-result-cls"></div>
  </span>


  </body>
</html>